package counter.com.baomidou.controller;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import counter.com.baomidou.entity.*;
import counter.com.baomidou.mapper.TargetinfoMapper;
import counter.com.baomidou.service.*;
import counter.com.common.Result;
import counter.com.connproperty.attackinfo.*;
import counter.com.myservice.PollingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author jobob
 * @since 2020-10-01
 */
@RestController
@RequestMapping("/attackinfo")
public class AttackinfoController {
    @Autowired
    IAttackinfoService attackinfoService;

    @Autowired
    IActivityinfoService activityinfoService;

    @Autowired
    IMethodinfoService methodinfoService;

    @Autowired
    ITargetinfoService targetinfoService;

    @Autowired
    TargetinfoMapper targetinfoMapper;

    @Autowired
    IVirtualmachineinfoService virtualmachineinfoService;

    @Autowired
    PollingService pollingService;

    @PostMapping("/search")
    public Result search(@RequestBody AttackSearchProperty data) {
        LambdaQueryWrapper<Attackinfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByDesc(true, Attackinfo::getId);
        Page<Attackinfo> page = new Page<>(data.getPage(), data.getPagesize());
        IPage<Attackinfo> iPage = attackinfoService.page(page, wrapper);
        List<Attackinfo> records = iPage.getRecords();
        List<AttackInfoResp> attackInfoResps = new ArrayList<>(data.getPagesize());
        addDataIntoResps(attackInfoResps, records);
        return Result.success(new AttackSearchRespProperty(iPage.getPages(), iPage.getCurrent(), iPage.getSize(), iPage.getTotal(), attackInfoResps));
    }


    @PostMapping("/add")
    public Result add(@RequestBody AttackAddProperty data) {
        Methodinfo methodinfo = methodinfoService.getById(data.getMid());
        if (data.getTids().length == 0) {
            return Result.fail("请检查是否给定了目标信息");
        }
        List<Targetinfo> targetinfos = targetinfoMapper.selectBatchIds(Arrays.asList(data.getTids()));
        Integer firstAttackId = 0;
        if (targetinfos.size() == 0 || methodinfo == null) {
            return Result.fail("请确认方法或者目标是否存在");
        } else {
            for (Targetinfo info :
                    targetinfos) {
                Attackinfo attackinfo = new Attackinfo();
                attackinfo.setMid(data.getMid());
                attackinfo.setTid(info.getId());
                attackinfo.setDstip(info.getIp());
                attackinfo.setCreatedtime(LocalDateTime.now());
                attackinfo.setProgress(0);
                attackinfoService.save(attackinfo);
                pollingService.addAttackIntoList(attackinfo);
                if (firstAttackId == 0) {
                    firstAttackId = attackinfo.getId();
                }
            }
            return Result.success(firstAttackId);
        }
    }

    @PostMapping("/delete")
    public Result delete(@RequestBody AttackDeleteProperty data) {
        if (attackinfoService.removeByIds(Arrays.asList(data.getIds()))) {
            return Result.success("删除成功");
        } else {
            return Result.fail("删除失败");
        }
    }

    /***
     * 生成虚假活动事件的接口
     */
    @PostMapping("/fake")
    public Result fake(@RequestBody AttackFakeProperty data) {
        Attackinfo attackinfo = attackinfoService.getById(data.getAid());
        if (attackinfo == null) {
            return Result.fail("没有找到合适的攻击信息");
        }
        Activityinfo activityinfo = new Activityinfo();
        activityinfo.setAid(data.getAid());
        activityinfo.setSrcip(data.getSrcip());
        activityinfo.setDstip(data.getDstip());
        activityinfo.setPort(data.getPort());
        activityinfo.setThread(data.getThread());
        activityinfo.setReason(data.getReason());
        if (activityinfoService.save(activityinfo)) {
            //保存activity如果成功
            attackinfo.setProgress(data.getProgress());
            attackinfoService.saveOrUpdate(attackinfo);
            return Result.success("添加活动，刷新状态成功");
        } else {
            return Result.fail("添加活动失败");
        }
    }

    @PostMapping("/detail")
    public Result detail(@RequestBody AttackDetailProperty data) {
        Attackinfo attackinfo = attackinfoService.getById(data.getId());
        if (attackinfo == null) {
            return Result.fail("未找到合适的信息");
        }
        Methodinfo methodinfo = methodinfoService.getById(attackinfo.getMid());
        Targetinfo targetinfo = targetinfoService.getById(attackinfo.getTid());
        if (methodinfo == null || targetinfo == null) {
            return Result.fail("请检查是否存在对应方法或者目标");
        }
        LambdaQueryWrapper<Activityinfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Activityinfo::getAid, attackinfo.getId());
        List<Activityinfo> activityinfos = activityinfoService.list(wrapper);
        return Result.success(new AttackDetailRespProperty(attackinfo.getProgress(), targetinfo, methodinfo, activityinfos, attackinfo.getCreatedtime(), virtualmachineinfoService.count()));
    }

    private void addDataIntoResps(List<AttackInfoResp> attackInfoResps, List<Attackinfo> records) {
        for (Attackinfo attackinfo :
                records) {
            AttackInfoResp obj = new AttackInfoResp();
            Targetinfo targetinfo = targetinfoService.getById(attackinfo.getTid());
            Methodinfo methodinfo = methodinfoService.getById(attackinfo.getMid());
            obj.setTargetinfo(targetinfo);
            obj.setMethodinfo(methodinfo);
            obj.setProgress(attackinfo.getProgress());
            obj.setCreatedtime(attackinfo.getCreatedtime());
            obj.setId(attackinfo.getId());
            attackInfoResps.add(obj);
        }
    }
}
